import asyncio
from asyncio.exceptions import  TimeoutError
async def play_music(musicname): # 模拟播放音乐的协程
    print(f'{musicname}-start play')
    await asyncio.sleep(5) # 模拟 播放音乐所消耗的时间
    print(f'{musicname}-finished play')
# 手动取消协程
async def main():
    task = asyncio.create_task(play_music('七里香')) # 将播放音乐的协程加入到执行队列
    await asyncio.sleep(3)
    if not task.done(): # 判断播放音乐的协程是不是已经执行完成了
        task.cancel() # 取消 协程任务

# 设置超时自动取消协程
async def main2():
    task = asyncio.create_task(play_music('七里香')) # 将播放音乐的协程加入到执行队列
    try:
        await asyncio.wait_for(task,3) # 使用 超时自动取消协程任务的方式的话，一旦超时取消，这个地方就会抛出timeError的异常，同时这个超时的协程会自动停掉。
    except  TimeoutError:
        print('超时自动取消了')
    print('main2 finished')

async def main3():
    task = asyncio.create_task(play_music('七里香')) # 将播放音乐的协程加入到执行队列
    try:
        await asyncio.wait_for(asyncio.shield(task),3) # 如果我们只是想知道这个协程的运行是不是超时了，而不需要超时以后就直接取消掉整个协程任务。那我们就需要使用 asyncio.shield 函数去创建盾牌，将这个协程保护起来，不让它被自动关闭
    except  TimeoutError:
        print('超时自动取消了')
    await task # 在这个地方需要等待一下 task 协程，不然音乐还没有播放完，整个线程就结束了。
    print('main3 finished')

# asyncio.run(main())
# asyncio.run(main2())
asyncio.run(main3())